package com.david.learning.algorithm;


/**
 * Caluclate the possible solution for 21 points
 * 
 * @author David Qi
 * 
 */
public class Point21 {
	private static final int[] CARDS = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
	private static final int RESULT = 21;
	private static final int CARD_NUMBER = 4;
	private static final Calculation[] METHODS = new Calculation[] { new AdditionCalculation(),
	        new MulitipleCalculation(), new SubstractionCalculation(), new DivisionCalculation() };

	public static void main(String[] args) {
		System.out.println(calculatePoints(0));
	}

	// TODO: delete repeat cards
	public static int calculatePoints(int currentPoints) {
		int sum = 0;
		
		for(int j=0; j<CARD_NUMBER; j++) {
			for(int i : CARDS) {
				for(Calculation m : METHODS) {
					System.out.println("current points : " + currentPoints + " current Card: " + i + " current method: " + m);
					try{
						sum += calculatePoints(m.calculate(currentPoints, i));
					}catch(Exception e) {
						return 0;
					}	
				}
			}
		}
		return sum;
	}
}

interface Calculation {
	public int calculate(int firstCard, int SecondCard);
}

class MulitipleCalculation implements Calculation {
	public int calculate(int firstCard, int secondCard) {
		return firstCard * secondCard;
	}
	public String toString() {
		return " * ";
	}
}

class AdditionCalculation implements Calculation {
	public int calculate(int firstCard, int secondCard) {
		return firstCard + secondCard;
	}
	
	public String toString() {
		return " + ";
	}
}

class SubstractionCalculation implements Calculation {
	public int calculate(int firstCard, int secondCard) {
		return firstCard - secondCard;
	}
	
	public String toString() {
		return " - ";
	}
}

class DivisionCalculation implements Calculation {
	public int calculate(int firstCard, int secondCard) {
		double dFirst = Double.valueOf(firstCard);
		double dSecond = Double.valueOf(secondCard);
		double dResult = dFirst / dSecond;
		int iResult = (int) dResult;
		double diff = dResult - iResult;
		if (diff > 0) {
			throw new RuntimeException("This way can't go!");
		}
		return iResult;
	}
	
	public String toString() {
		return " / ";
	}
}